package com.h2View.controller;

import com.h2View.db.dao.SqlMapper;
import com.h2View.entity.MsgBox;
import com.h2View.entity.TableColumns;
import com.h2View.exception.ServiceException;
import com.h2View.utils.CacheUtil;
import com.h2View.utils.MybatisUtils;
import com.h2View.utils.SqlUtil;
import com.h2View.utils.StringUtil;
import com.h2View.utils.ToolConstant;
import com.h2View.utils.ToolUtil;
import com.xjw.annotation.FXController;
import com.xjw.annotation.FXRedirect;
import com.xjw.annotation.FXWindow;
import com.xjw.entity.FXBaseController;

import cn.hutool.core.io.FileUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.ListView;
import javafx.scene.control.RadioButton;
import javafx.scene.control.TableView;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.input.MouseEvent;
import javafx.scene.text.Text;

import java.awt.Desktop;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.ResourceBundle;

/**
 * @author xwx1052336
 * @since iFad Platform V100R001,2021/8/24
 */
@FXController(path = "fxml/function.fxml")
@FXWindow( title = "功能", icon = "image/icon.png")
public class FunctionController extends FXBaseController implements Initializable {

    private Log log = LogFactory.get();

    @FXML
    private ListView<String> tablesEle;

    @FXML
    private TextField filtEle;

    @FXML
    private TableView<TableColumns> tableCloumnsEle;

    @FXML
    private TableView<LinkedHashMap<String,Object>> dataEle;

    private static ObservableList<LinkedHashMap<String,Object>> dataList = FXCollections.observableArrayList();

    private ObservableList<String> list = FXCollections.observableArrayList();
    private ObservableList<String> globList = FXCollections.observableArrayList();
    private ObservableList<TableColumns> tableCloumns = FXCollections.observableArrayList();

    @FXML
    private TextArea whereEle;

    @FXML
    private Text msgEle;

    @FXML
    private Text countEle;

    @FXML
    private RadioButton copyBtnEle;

    private static String tableName = "";

    private String line = System.getProperty("line.separator");

    private File sqlFile = new File("config/export.sql");

    {
        try{
            if(!sqlFile.exists()){
                if(!sqlFile.getParentFile().exists()) {
                    if (!sqlFile.getParentFile().mkdirs()) {
                        throw new ServiceException(sqlFile.getParentFile().getAbsolutePath() + "目录创建失败");
                    }
                }
                if(!sqlFile.createNewFile()){
                    throw new ServiceException(sqlFile.getAbsolutePath() + "文件创建失败");
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        tablesEle.setItems(list);
        tableCloumnsEle.setItems(tableCloumns);
        dataEle.setItems(dataList);
        filtEle.textProperty().addListener((observable, oldValue, newValue) -> filtering(newValue));
    }

    @Override
    public void onShow(){
        SqlUtil.setDataType();
        reloadTables();
    }

    @FXRedirect
    public String jumpLogin(){
        return "LoginController";
    }

    private void reloadTables(){
        ToolUtil.execAsync(()->{
            list.clear();
            globList.clear();
            SqlMapper sqlMapper = MybatisUtils.getMapper(SqlMapper.class);
            List<LinkedHashMap<String,Object>> tables = sqlMapper.customQueryItem(SqlUtil.getAllTablesSql());
            for(LinkedHashMap<String,Object> tableMap:tables){
                list.add(tableMap.get(SqlUtil.getTableName()).toString());
            }
            globList.addAll(list);
            filtering(filtEle.getText());
        });
    }

    private  List<LinkedHashMap<String,Object>> find(String sql){
        SqlMapper sqlMapper = MybatisUtils.getMapper(SqlMapper.class);
        return sqlMapper.customQueryItem(sql);
    }




    @FXRedirect
    public String jumpMain(){
        return "MainController";
    }

    @FXML
    @FXRedirect(close = false)
    public String deleteTable(){
        MsgBox msgBox = new MsgBox();
        Runnable runnable = () -> {
            String tableName = tablesEle.getSelectionModel().getSelectedItem();
            String sql = "DROP TABLE IF EXISTS "+tableName;
            if(ToolUtil.excute(sql)){
                reloadTables();
                setMsg(tableName+"删除成功");
            }
        };
        msgBox.setRunnable(runnable);
        msgBox.setMsg("请确认是否要删除表："+tablesEle.getSelectionModel().getSelectedItem());
        msgBox.setSendUrl("FunctionController");
        msgBox.setReciveUrl("ConfirmBarController");
        CacheUtil.put(ToolConstant.MSGBOX+msgBox.getReciveUrl(),msgBox);
        return msgBox.getReciveUrl();
    }

    private void filtering(String filtText){
        list.clear();
        if(com.h2View.utils.StringUtil.isEmpty(filtText)){
            list.addAll(globList);
        }
        ObservableList<String> temp = FXCollections.observableArrayList();
        globList.forEach((String tableName)->{
            if(tableName.toLowerCase().contains(filtText.toLowerCase())){
                temp.add(tableName);
            }
        });
        list.addAll(temp);
    }

    @FXML
    private void showColumns(){
        ToolUtil.execAsync(()->{
            initTableCloumns();
        });
    }

    private String getSelectSql(){
        String whereStr = whereEle.getText();
        return "select * from " + tableName + (StringUtil.isEmpty(whereStr) ? "" : " where " + whereStr) + " limit 500";
    }

    @FXML
    public void showTableData(){
        tableName = tablesEle.getSelectionModel().getSelectedItem();
        ToolUtil.execAsync(()->{
            try{
                dataEle.getColumns().clear();
                dataList.clear();
                String sqlColumns = SqlUtil.getTablesColumns(tableName);
                List<LinkedHashMap<String,Object>> result = find(sqlColumns);
                for(LinkedHashMap<String,Object> table:result){
                    ToolUtil.addTableColumns(table.get("FIELD") == null ?
                        table.get("field").toString(): table.get("FIELD").toString(),dataEle);
                }
                String sql = getSelectSql();
                List<LinkedHashMap<String,Object>> resultMap = find(sql);

                if(resultMap == null || resultMap.size() == 0){
                   return;
                }
                dataList.addAll(resultMap);
                countEle.setText(dataList.size()+"");
            }catch (Exception e){
                log.error(e);
                setMsg("请检查wherey语句");
            }
        });
    }

    @FXML
    private void dataFiltEle(){
        showTableData();
    }

    @FXML
    private void getTableName(MouseEvent event){
        if(event.getClickCount()==2&&event.getButton().name().equals("PRIMARY")){
            TableColumns tableColumns = tableCloumnsEle.getSelectionModel().getSelectedItem();
            if(tableColumns == null){
                return;
            }
            String tableName = tableColumns.getField();
            whereEle.setText(whereEle.getText()+tableName);
        }else if(event.getClickCount()==1&&event.getButton().name().equals("PRIMARY")){
            ToolUtil.copyValue(tableCloumnsEle);
        }
    }

    private void setMsg(String msg){
       setMsg(msg,5000);
    }

    private void setMsg(String msg,long time){
        if(StringUtil.isEmpty(msg)){
            return;
        }
        msgEle.setVisible(true);
        msgEle.setText(msg);
        ToolUtil.execAsync(()-> msgEle.setVisible(false),time);
    }

    @FXML
    private void reloadSession(){
        try{
            MybatisUtils.reLoadSession();
            tableName = tablesEle.getSelectionModel().getSelectedItem();
            if(StringUtil.isNotEmpty(tableName)){
                showTableData();
                showColumns();
            }
            reloadTables();
            setMsg("重新加载成功",2000);
        }catch (Exception e){
            log.error(e);
            setMsg("重新加载失败");
        }
    }

    @FXML
    @FXRedirect(close = false)
    public String truncateTable(){
        MsgBox msgBox = new MsgBox();
        tableName = tablesEle.getSelectionModel().getSelectedItem();
        Runnable runnable = () -> {
            String sql = "truncate table " + tableName;
            if(ToolUtil.excute(sql)){
                showTableData();
                setMsg("表数据清理成功");
            }else{
                setMsg("表数据清理失败");
            }
        };
        msgBox.setRunnable(runnable);
        msgBox.setMsg("请确认是否要清空该表："+tableName);
        msgBox.setSendUrl("FunctionController");
        msgBox.setReciveUrl("ConfirmBarController");
        CacheUtil.put(ToolConstant.MSGBOX+msgBox.getReciveUrl(),msgBox);
        return msgBox.getReciveUrl();
    }

    @FXML
    @FXRedirect(close = false)
    public String updateData(){
        LinkedHashMap<String,Object> data = dataEle.getSelectionModel().getSelectedItem();
        if(ToolUtil.isEmpty(data)){
            return "FunctionCotroller";
        }
        String sqlColumns = SqlUtil.getTablesColumns(tableName);
        List<LinkedHashMap<String,Object>> result = find(sqlColumns);
        for(LinkedHashMap<String,Object> table:result){
            String key = table.get("FIELD") == null ?
                table.get("field").toString(): table.get("FIELD").toString();
            // 如果data的key为null则放入key
            data.putIfAbsent(key, null);
        }
        CacheUtil.put("dataController",data);
        CacheUtil.put("tableName",tableName);
        CacheUtil.put("type",ToolConstant.UPDATEDATA);
        CacheUtil.put("FunctionController",this);
        DataController.flag = false;
        return "DataController";
    }

    @FXML
    @FXRedirect(close = false)
    public String createData(){
        initTableCloumns();
        LinkedHashMap<String,Object> data = new LinkedHashMap<>(tableCloumns.size());
        for(TableColumns tableColumns:tableCloumns){
            data.put(tableColumns.getField(),null);
        }
        CacheUtil.put("dataController",data);
        CacheUtil.put("tableName",tableName);
        CacheUtil.put("type", ToolConstant.CREATEDATA);
        CacheUtil.put("FunctionController",this);
        DataController.flag = false;
        return "DataController";
    }

    private void initTableCloumns(){
        String tableName = tablesEle.getSelectionModel().getSelectedItem();
        if(StringUtil.isEmpty(tableName)){
            if(list.size() != 0){
                tableName = list.get(0);
            }else{
                String msg = "当前页面没有数据表";
                setMsg(msg);
                throw new ServiceException(msg);
            }

        }
        String sql = SqlUtil.getTablesColumns(tableName);
        List<LinkedHashMap<String,Object>> result = find(sql);
        tableCloumns.clear();
        for(LinkedHashMap<String,Object> tableMap:result){
            TableColumns tableColumn = ToolUtil.mapToBean(tableMap,TableColumns.class);
            tableCloumns.add(tableColumn);
        }
    }

    @FXML
    @FXRedirect(close = false)
    public String deleteData(){
        MsgBox msgBox = new MsgBox();
        Runnable runnable = () -> {
            String sql = SqlUtil.deleteSql(tableName, dataEle.getSelectionModel().getSelectedItem());
            if(ToolUtil.excute(sql)){
                showTableData();
            }else{
                setMsg("数据删除失败！");
            }
        };
        msgBox.setRunnable(runnable);
        msgBox.setMsg("请确认是否要删除该数据："+dataEle.getSelectionModel().getSelectedItem());
        msgBox.setSendUrl("FunctionController");
        msgBox.setReciveUrl("ConfirmBarController");
        CacheUtil.put(ToolConstant.MSGBOX+msgBox.getReciveUrl(),msgBox);
        return msgBox.getReciveUrl();
    }


    @FXML
    private void exportSql(){
        if(dataList.size() == 0){
            return;
        }
        StringBuilder sqlStr = new StringBuilder();
        for(LinkedHashMap<String,Object> entry:dataList){
            sqlStr.append(SqlUtil.insertSql(tableName,entry));
            sqlStr.append(line);
        }
        FileUtil.appendString(sqlStr.toString(),sqlFile,"UTF-8");
        try {
            Desktop.getDesktop().open(sqlFile);
        } catch (IOException e) {
            setMsg(e.getMessage());
        }
    }

    @FXML
    private void dataCopyValue() {
        ToolUtil.copyValue(dataEle);
    }

    @FXML
    private void copyTableName(){
        ToolUtil.copyValue(tablesEle);
    }

    @FXML
    private void dataClick(MouseEvent event){
        if(event.getClickCount()==2&&event.getButton().name().equals("PRIMARY")){
            if(dataList.size() == 0){
                createData();
            }else{
                updateData();
            }
        }else if(event.getClickCount()==1&&event.getButton().name().equals("PRIMARY")){
            ToolUtil.copyValue(dataEle);
        }
    }

    @FXML
    private void tableClick(MouseEvent event){
        if(event.getClickCount()==2&&event.getButton().name().equals("PRIMARY")){
            showTableData();
        }else if(event.getClickCount()==1&&event.getButton().name().equals("PRIMARY")){
            ToolUtil.copyValue(tablesEle);
        }
    }

    @FXML
    private void copyBtn(){
        ToolUtil.copyFlag = copyBtnEle.isSelected();
    }


}
